<!doctype html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
    <script type="text/javascript">
      const tokenLifetimeDays = 7;

      const getParameterByName = (name) => {
        return new URLSearchParams(location.search).get(name);
      };

      const setAuthData = (data) => {
        const storageType = getParameterByName('storageType') || 'localStorage';
        switch (storageType) {
          case 'localStorage':
          case 'sessionStorage':
            window[storageType].setItem('luigi.auth', JSON.stringify(data));
            window[storageType].setItem('luigi.newlyAuthorized', true);
            break;
          default:
            console.error(
              'Configuration Error: Invalid auth.storage setting. Must be either localStorage or sessionStorage to be used with OAuth2 Provider.',
            );
        }
      };

      const getHashParams = () => {
        let hash = encodeURIComponent(window.location.hash.substring(1));
        return decodeURIComponent(hash)
          .split('&')
          .reduce(function (result, item) {
            var parts = item.split('=');
            result[parts[0]] = parts[1];
            return result;
          }, {});
      };

      const processExpDate = (expiresInString) => {
        let expirationDate;
        const expiresIn = Number(expiresInString);
        if (!isNaN(expiresIn) && expiresIn > 0) {
          const nsToMsMultiplier = 1000;
          expirationDate =
            Number(new Date()) + nsToMsMultiplier * (expiresIn - tokenLifetimeDays);
        }
        return expirationDate;
      };

      const parseJwt = (token) => {
        const base64Url = token.split('.')[1];
        const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
        const jsonPayload = decodeURIComponent(
          atob(base64)
            .split('')
            .map(function (c) {
              return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
            })
            .join(''),
        );

        return JSON.parse(jsonPayload);
      };
    </script>
  </head>

  <body>
    <script type="text/javascript">
      const uri = encodeURIComponent(window.location.href);
      const hashParams = getHashParams(uri);
      const token = hashParams['access_token'] || hashParams['id_token'];
      if (hashParams && (token || hashParams['error'])) {
        const error = hashParams['error'];
        const { exp } = parseJwt(hashParams['id_token']);
        const expires_in = hashParams['expires_in'] || exp;
        if (!error) {
          const data = {
            accessToken: token,
            accessTokenExpirationDate: processExpDate(expires_in),
            scope: hashParams['scope'],
            idToken: hashParams['id_token'],
          };

          setAuthData(data);

          const decodedState = atob(decodeURIComponent(hashParams['state'])).split(
            '_luigiNonce=',
          );
          const appState = decodeURI(decodedState[0] || '');
          const nonce = decodedState[1];

          if (nonce !== sessionStorage.getItem('luigi.nonceValue')) {
            document.getElementsByTagName('body')[0].innerHTML =
              'Something went wrong. Try to log in again.';
            throw new Error(
              'State parameter returned from the authorization endpoint does not match locally stored state. Aborting login process.',
            );
          }

          const appStateUrl = new URL(appState);
          if (appStateUrl.origin === window.location.origin) {
            const newUrl = new URL(window.location.href);
            newUrl.pathname = appStateUrl.pathname;
            newUrl.search = appStateUrl.search;
            newUrl.hash = appStateUrl.hash;
            window.location.href = newUrl.href;
          } else {
            window.location.href = '/';
            console.log(
              `Preventing redirect to ${appState} as it does not match the current origin.`,
            );
          }
        } else {
          // else tree only applies to idtoken auths, I guess
          const errorDescription = hashParams['error_description'];
          console.error('error', errorDescription);
          const params = new URLSearchParams();
          params.set('error', error);
          params.set('errorDescription', errorDescription);
          const url = new URL('/', window.location.href);
          url.search = params;
          window.location.href = url.href;
        }
      }
    </script>
  </body>
</html>
